#include <windows.h>
#include <stdio.h>
#include <chrono>
#include <thread>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <signal.h>

using namespace std;
#define BAUD_RATE CBR_115200
#define PORT_NAME "COM2"
#define BUFFER_SIZE 1024
char send_buffer[BUFFER_SIZE];
char send_hex[2];
unsigned int sum = 0;

uint8_t ascii_buffer[BUFFER_SIZE];
const static uint8_t bd_cmd_header[2] = "$";       /* 帧头 */
const static uint8_t bd_cmd_get_id[6] = "CCICR";   /* 获取卡号  */
const static uint8_t bd_cmd_sent[6] = "CCTCQ";     /* 发送报文  */
const static uint8_t bd_cmd_test[6] = "BDMCH";     /* 检测工况  */
const static uint8_t bd_cmd_split[1] = {0x2C};     /* 分割用逗号  */
const static uint8_t bd_dest_id[8] = "1150002";    /* 收信方ID  */
const static uint8_t bd_lf_id[2] = "2";            /* 入站频点  */
const static uint8_t bd_answer[2] = "1";           /* 不需确认  */
const static uint8_t bd_encode[2] = "3";           /* 编码类别  1.内码 2.ASC 3.混编*/
const static uint8_t bd_freq[2] = "0";             /* 频度  */
const static uint8_t bd_cmd_end[2] = {0x0D, 0x0A}; /* 结尾  */
const static uint8_t bd_star[1] = {0x2A};          /* *  */
uint8_t bd_cmd_sum[1] = {0x00};                    /* 和校验  */

HANDLE hSerial;
/*******************************************************************
 * 名称： OpenSerialPort
 * 功能： 打开串口
 * 参数： 串口句柄
 * 返回： 串口句柄
 *******************************************************************/
HANDLE OpenSerialPort(const char *portName)
{
    HANDLE hSerial = CreateFileA(portName, GENERIC_READ | GENERIC_WRITE,
                                 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hSerial == INVALID_HANDLE_VALUE)
    {
        printf("Error opening serial port: %d\n", GetLastError());
        return INVALID_HANDLE_VALUE;
    }
    return hSerial;
}
/*******************************************************************
 * 名称： closeComm
 * 功能： 关闭串口
 * 参数： 无
 * 返回： 正确返回为ture，错误返回为false
 *******************************************************************/
void CloseSerialPort()
{
    if (NULL == hSerial)
        return;
    CloseHandle(hSerial);
    hSerial = NULL;
}
/*******************************************************************
 * 名称： SetupSerialPort
 * 功能： 配置串口
 * 参数： 串口句柄
 * 返回： 正确返回为ture，错误返回为false
 *******************************************************************/
BOOL SetupSerialPort(HANDLE hSerial)
{
    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength = sizeof(DCB);

    // 获取当前串口设置并修改
    if (!GetCommState(hSerial, &dcbSerialParams))
    {
        printf("Error getting current serial port settings: %d\n", GetLastError());
        CloseHandle(hSerial);
        return FALSE;
    }

    // 设置波特率和其他参数
    dcbSerialParams.BaudRate = BAUD_RATE;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;

    if (!SetCommState(hSerial, &dcbSerialParams))
    {
        printf("Error setting serial port parameters: %d\n", GetLastError());
        CloseHandle(hSerial);
        return FALSE;
    }

    // 设置超时参数
    COMMTIMEOUTS timeouts;
    timeouts.ReadIntervalTimeout = MAXDWORD;
    timeouts.ReadTotalTimeoutMultiplier = 0;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;

    if (!SetCommTimeouts(hSerial, &timeouts))
    {
        printf("Error setting timeouts: %d\n", GetLastError());
        CloseHandle(hSerial);
        return FALSE;
    }

    return TRUE;
}

/*******************************************************************
 * 名称： WriteToSerialPort
 * 功能： 发送数据到串口
 * 参数： 串口句柄，需要发送的数据
 * 返回： 正确返回为ture，错误返回为false
 *******************************************************************/
BOOL WriteToSerialPort(HANDLE hSerial, const char *data)
{
    DWORD bytesWritten;
    if (!WriteFile(hSerial, data, strlen(data), &bytesWritten, NULL))
    {
        printf("Error writing to serial port: %d\n", GetLastError());
        return FALSE;
    }
    return TRUE;
}

/*******************************************************************
 * 名称： ReadFromSerialPort
 * 功能： 从串口读取数据
 * 参数： 串口句柄，缓存区，大小
 * 返回： 正确返回为ture，错误返回为false
 *******************************************************************/
BOOL ReadFromSerialPort(HANDLE hSerial, char *buffer, DWORD size)
{
    DWORD bytesRead;
    if (!ReadFile(hSerial, buffer, size, &bytesRead, NULL))
    {
        printf("Error reading from serial port: %d\n", GetLastError());
        return FALSE;
    }
    buffer[bytesRead] = '\0'; // 添加结束符以形成字符串
    return TRUE;
}
/*******************************************************************
 * 名称： TimerProc
 * 功能： 发送当前时间数据到串口
 * 参数： 串口句柄
 * 返回： 无
 *******************************************************************/
VOID CALLBACK TimerProc(HANDLE hSerial)
{
    if (hSerial)
    {
        char sendData[] = "Hello, World!";
        WriteToSerialPort(hSerial, sendData);
        char receiveBuffer[BUFFER_SIZE];
    }
}
/*******************************************************************
 * 名称： checksum
 * 功能： 计算数据异或和校验
 * 参数： 数据
 * 返回： 异或和
 *******************************************************************/
unsigned int checksum(char *str)
{
    sum = 0;
    if (&str[0] == "$")
    {
        str++;
    } //  跳过第一个字符
    while (*str)
    {
        sum ^= *str;
        str++;
    }
    return sum;
}

/*******************************************************************
 * 名称： char_to_hex
 * 功能： 用于将一个字符转化为ASCII码十六进制表示
 * 参数： 数据
 * 返回： ASCII码十六进制
 *******************************************************************/
char *char_to_hex(char *c)
{
    // 创建一个长度为 3 的字符串，用于存储结果
    // char* hex;
    // 使用 sprintf 函数，将字符 c 的 ASCII 码转化为十六进制，并存储在 hex 中
    sprintf(send_hex, "%02X", *c);
    // scanf(c,"s%",hex);
    //  返回 hex
    return send_hex;
}
//
/*******************************************************************
 * 名称： ArrayToHex
 * 功能： 用于将字符串转化为十六进制表示
 * 参数： 数据，长度
 * 返回： 数据指针
 *******************************************************************/
uint8_t *ArrayToHex(char *para, int lenth)
{
    for (int i = 0; i < lenth; i++)
    {
        memcpy(&ascii_buffer[i * 2], char_to_hex(para + i), 2);
    }
    return ascii_buffer;
}

/*******************************************************************
 * 名称： bd_message_sent
 * 功能： 用于将北斗短报文发送到串口
 * 参数： 串口句柄，数据，长度
 * 返回： 无
 *******************************************************************/
void bd_message_sent(HANDLE hSerial, uint8_t *param, int lenth)
{
    int offset = 0;
    memset(&send_buffer, 0, sizeof(send_buffer));
    memcpy(send_buffer + offset, bd_cmd_header, 1);
    offset += sizeof(bd_cmd_header) - 1;
    memcpy(send_buffer + offset, bd_cmd_sent, 5); //  通信申请
    offset += sizeof(bd_cmd_sent) - 1;
    memcpy(send_buffer + offset, bd_cmd_split, 1);
    offset += sizeof(bd_cmd_split);
    memcpy(send_buffer + offset, bd_dest_id, sizeof(bd_dest_id)); //  收信方 ID
    offset += sizeof(bd_dest_id) - 1;
    memcpy(send_buffer + offset, bd_cmd_split, 1);
    offset += sizeof(bd_cmd_split);
    memcpy(send_buffer + offset, bd_lf_id, 1); //  频点
    offset += sizeof(bd_lf_id) - 1;
    memcpy(send_buffer + offset, bd_cmd_split, 1);
    offset += sizeof(bd_cmd_split);
    memcpy(send_buffer + offset, bd_answer, 1); //   入站确认申请
    offset += sizeof(bd_answer) - 1;
    memcpy(send_buffer + offset, bd_cmd_split, 1);
    offset += sizeof(bd_cmd_split);
    memcpy(send_buffer + offset, bd_encode, 1); //   编码类别
    offset += sizeof(bd_encode) - 1;
    memcpy(send_buffer + offset, bd_cmd_split, 1);
    offset += sizeof(bd_cmd_split);
    if (bd_encode[0] == 51)
    {
        memcpy(send_buffer + offset, "A4", 2); //   编码类别3时增加A4头
        offset += 2;
    }
    memcpy(send_buffer + offset, param, lenth - 2); //   通信数据
    offset += lenth - 2;
    memcpy(send_buffer + offset, bd_cmd_split, 1);
    offset += sizeof(bd_cmd_split);
    memcpy(send_buffer + offset, bd_freq, 1); //   报文通信频度
    offset += sizeof(bd_freq) - 1;
    bd_cmd_sum[0] = checksum(send_buffer);
    sprintf(send_hex, "%x", *bd_cmd_sum);
    memcpy(send_buffer + offset, bd_star, 1);
    offset += sizeof(bd_star);
    memcpy(send_buffer + offset, send_hex, 2); //  校验和
    offset += 2;
    memcpy(send_buffer + offset, bd_cmd_end, 2); //  结尾
    //  rt_device_write(bd_serial, 0, send_buffer, 1024);
    WriteToSerialPort(hSerial, send_buffer);
}

void CALLBACK timer_handler(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    printf("Timer expired!\n");
}

// 数据处理中的定时器函数
void (*data_processing_timer)(void);

// 定时器函数
void on_data_processing_timer(void)
{
    printf("数据处理定时器事件发生\n");
    // 执行数据处理任务
    // ...
}

void handler(int signum)
{
    printf("Timer expired\n");
}

int main()
{
    // 读取RDSS2IC卡信息
    const char *bd_read_rdss2 = "$CCICA,0,00*7B\r\n";
    // 读取RDSS3IC卡信息
    const char *bd_read_rdss3 = "$CCICR,0,00*68\r\n";
    // 关闭所有语句
    const char *bd_close_all  = "$$CCRMO,,3,1*7E\r\n"; 
    // 打开RMC，频率1秒
    const char *bd_open_rmc = "$CCRMO,RMC,2,1*23\r\n";
    char testchar[] = "CCRMO,RMC,2,1";
    HANDLE hSerial = OpenSerialPort(PORT_NAME);
    uint8_t param[] = "$GNRMC,072930.000,A,3412.169361,N,10855.447472,E,0.000,133.580,190916,1,0,52,0000,00,1,2172288,1*";
    char para1[] = "$GNRMC,072930.000,A,3412.169361,N,10855.447472,E,0.000,133.580,190916,1,0,52,0000,00,1,2172288,1*21";
    uint8_t *aChar = ArrayToHex(para1, sizeof(para1));
    if (hSerial != INVALID_HANDLE_VALUE)
    {
        if (SetupSerialPort(hSerial))
        {
            int i = 0;
            while (i < 10)
            {
                char time1[32];
                // 使用ctime获取当前时间
                std::time_t now = std::time(nullptr);
                // std::cout << "当前时间：" << std::ctime(&now);
                std::tm *now_tm = std::localtime(&now);
                strftime(time1, 32, "SentTime:%Y.%m.%d %H:%M:%S\r\n", now_tm);
                WriteToSerialPort(hSerial, time1);
                WriteToSerialPort(hSerial, bd_read_rdss3);
                Sleep(100);
                bd_message_sent(hSerial, aChar, sizeof(para1) * 2 - 1);
                char receiveBuffer[BUFFER_SIZE];
                ReadFromSerialPort(hSerial, receiveBuffer, BUFFER_SIZE);
                printf("Received: %s%s\n", receiveBuffer, std::ctime(&now));
                Sleep(1000);
                i++;
            }
            CloseHandle(hSerial);
        }
    }
    exit(NULL);
    return 0;
}
